﻿using System;
using System.Threading;
using System.Globalization;
using TheBigB.JsonSerializerLite;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Tester
{
	/// 
	/// Serializer tool tests.
	/// 
	/// Runs input tests on the serialization tools.
	/// 
	/// Changelog:
	///		2012-09-07
	///			- Added tests for unicode escaping
	///		

	/// <summary>
	/// Serializer tool tests.
	/// </summary>
	[TestClass]
	public class SerializationToolsTests
	{
		/// <summary>
		/// Tests whether the string escaper works properly.
		/// </summary>
		[TestMethod]
		public void TestStringEscaping()
		{
			string input, output, expected;

			input = null;
			expected = "";
			output = JsonSerializer.Default.EscapeString(input);
			Assert.AreEqual(expected, output, "Null input value is not being handled properly");

			input = "\"";
			expected = "\\\"";
			output = JsonSerializer.Default.EscapeString(input);
			Assert.AreEqual(expected, output, "Quotation marks are not being escaped properly");

			input = "\\";
			expected = "\\\\";
			output = JsonSerializer.Default.EscapeString(input);
			Assert.AreEqual(expected, output, "Reverse solidi are not being escaped properly");

			input = "/";
			expected = "\\/";
			output = JsonSerializer.Default.EscapeString(input);
			Assert.AreEqual(expected, output, "Solidi are not being escaped properly");

			input = "\b";
			expected = "\\b";
			output = JsonSerializer.Default.EscapeString(input);
			Assert.AreEqual(expected, output, "Backspace characters are not being escaped properly");

			input = "\f";
			expected = "\\f";
			output = JsonSerializer.Default.EscapeString(input);
			Assert.AreEqual(expected, output, "Formfeed characters are not being escaped properly");

			input = "\n";
			expected = "\\n";
			output = JsonSerializer.Default.EscapeString(input);
			Assert.AreEqual(expected, output, "Newline characters are not being escaped properly");

			input = "\r";
			expected = "\\r";
			output = JsonSerializer.Default.EscapeString(input);
			Assert.AreEqual(expected, output, "Carriage return characters are not being escaped properly");

			input = "\t";
			expected = "\\t";
			output = JsonSerializer.Default.EscapeString(input);
			Assert.AreEqual(expected, output, "Horizontal tab characters are not being escaped properly");

			// Character that require escaping: U+0000 to U+0007, U+000B, U+000E to U+001E
			// The others are escape by shortcut. E.g.: \t, \n
			input = "\x00\x01\x02\x03\x04\x05\x06\x07\x0b\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e";
			expected = @"\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u000b\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e";
			output = JsonSerializer.Default.EscapeString(input);
			Assert.AreEqual(expected, output, "The lower 32 ASCII character that require escaping are not being escaped properly");

			// Characters higher than U+00FF (Unicode) need to be escaped
			input = "\u0100\uc0c0\u04a9\u1234\u0444";
			expected = @"\u0100\uc0c0\u04a9\u1234\u0444";
			output = JsonSerializer.Default.EscapeString(input);
			Assert.AreEqual(expected, output, "Unicode characters are not being escaped properly");

			// Make sure high ASCII characters are not escaped
			input = "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ";
			expected = "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ";
			output = JsonSerializer.Default.EscapeString(input);
			Assert.AreEqual(expected, output, "High ASCII characters are unnecessarily being escaped");

			input = "abcd";
			expected = "abcd";
			output = JsonSerializer.Default.EscapeString(input);
			Assert.AreEqual(expected, output, "Regular strings are being escaped");
		}

		/// <summary>
		/// Tests the double string conversion amongst cultures with different decimal separator
		/// </summary>
		[TestMethod]
		public void TestDoubleConversion()
		{
			double input;
			string output, expected;

			input = 123.456;
			expected = "123.456";

			// Test in Dutch culture; ',' is the decimal separator
			Thread.CurrentThread.CurrentCulture = new CultureInfo("nl-NL");
			output = JsonSerializer.Default.SerializeValue(input, typeof(double));
			Assert.AreEqual(expected, output, "Double values are being converted incorrectly in the nl-NL culture");

			// Test in US-English culture; '.' is the decimal separator
			Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
			output = JsonSerializer.Default.SerializeValue(input, typeof(double));
			Assert.AreEqual(expected, output, "Double values are being converted incorrectly in the en-US culture");
		}

		/// <summary>
		/// Tests whether the given string is escaped and enclosed in quotation marks.
		/// </summary>
		[TestMethod]
		public void TestStringConversion()
		{
			string input, output, expected;

			// Test if quotation marks are added
			input = "abcd";
			expected = "\"abcd\"";
			output = JsonSerializer.Default.SerializeValue(input, typeof(string));
			Assert.AreEqual(expected, output, "Strings are not being enclosed in quotation marks");

			// Test if string is escaped
			input = "ab/c\\d";
			expected = "\"ab\\/c\\\\d\"";
			output = JsonSerializer.Default.SerializeValue(input, typeof(string));
			Assert.AreEqual(expected, output, "Strings are not being escaped and/or being enclosed in quotation marks.");
		}

		/// <summary>
		/// Tests whether the given character is escaped and enclosed in quotation marks.
		/// </summary>
		[TestMethod]
		public void TestCharConversion()
		{
			char input;
			string output, expected;

			// Test if quotation marks are added
			input = 'a';
			expected = "\"a\"";
			output = JsonSerializer.Default.SerializeValue(input, typeof(char));
			Assert.AreEqual(expected, output, "Chars are not being enclosed in quotation marks");

			// Test if string is escaped
			input = '\n';
			expected = "\"\\n\"";
			output = JsonSerializer.Default.SerializeValue(input, typeof(char));
			Assert.AreEqual(expected, output, "Chars are not being escaped and/or being enclosed in quotation marks.");
		}

		/// <summary>
		/// Tests whether the given boolean is converted properly to its string representation.
		/// </summary>
		[TestMethod]
		public void TestBoolConversion()
		{
			bool input;
			string output, expected;

			// Test true
			input = true;
			expected = "true";
			output = JsonSerializer.Default.SerializeValue(input, typeof(bool));
			Assert.AreEqual(expected, output, "Boolean 'true' value is not being converted properly");

			// Test false
			input = false;
			expected = "false";
			output = JsonSerializer.Default.SerializeValue(input, typeof(bool));
			Assert.AreEqual(expected, output, "Boolean 'false' value is not being converted properly");
		}

		/// <summary>
		/// Tests whether non-value-types return 'null'
		/// </summary>
		[TestMethod]
		public void TestNullConversion()
		{
			TestObject input;
			string output, expected;

			// Test object
			input = new TestObject();
			expected = "null";
			output = JsonSerializer.Default.SerializeValue(input, typeof(TestObject));
			Assert.AreEqual(expected, output, "Objects types are not returning 'null' for method SerializeValue()");
		}
	}
}
